CSRF (Cross-Site Request Forgery) হল একটি সাধারণ ওয়েব নিরাপত্তা আক্রমণ যেখানে একটি দুষ্টু ওয়েবসাইট ব্যবহারকারীর ব্রাউজারে অন্য ওয়েবসাইটে অননুমোদিত অনুরোধ পাঠায় যেখানে ব্যবহারকারী ইতিমধ্যেই লগইন করেছেন। Spring Security ডিফল্টভাবে CSRF Protection সক্রিয় রাখে, যা এমন আক্রমণ প্রতিরোধে সাহায্য করে।
1. CSRF Protection কিভাবে কাজ করে?
CSRF Protection মূলত একটি CSRF Token এর মাধ্যমে কাজ করে।
- Spring Security একটি Random Token তৈরি করে এবং এটি HTTP Request এর সাথে যাচাই করে।
- এই Token সাধারণত একটি Hidden Field হিসাবে ফর্মের সাথে পাঠানো হয় বা HTTP Header এ যুক্ত হয়।
- যদি টোকেন মেল না খায়, তাহলে Spring Security অনুরোধটি ব্লক করে।
2. Spring Security তে CSRF Protection ডিফল্ট কনফিগারেশন
Spring Security CSRF Protection ডিফল্টভাবে সক্রিয়। তাই কোনো অতিরিক্ত কনফিগারেশন প্রয়োজন হয় না যদি এটি ডিফল্ট ব্যবহার করা হয়।
Example Configuration:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf(); // Default CSRF Protection enabled
}
}
3. CSRF Token ব্যবহার এবং ফ্রন্টএন্ডে পাঠানো
CSRF Token ফ্রন্টএন্ড বা ফর্মে পাঠানোর জন্য Spring Security দুটি পদ্ধতি সরবরাহ করে:
Hidden Field (HTML Form): CSRF টোকেনটি একটি Hidden Field হিসাবে পাঠানো হয়।
উদাহরণ (Thymeleaf):
<form action="/submit" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> <button type="submit">Submit</button> </form>HTTP Header (AJAX): যদি API বা AJAX কলের জন্য CSRF Protection প্রয়োজন হয়, তাহলে টোকেন HTTP Header এ পাঠাতে হবে।
উদাহরণ (JavaScript):
const csrfToken = document.querySelector('meta[name="_csrf"]').content; const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content; fetch('/api/submit', { method: 'POST', headers: { [csrfHeader]: csrfToken, 'Content-Type': 'application/json' }, body: JSON.stringify({ data: "example" }) });এখানে টোকেন মেটা ট্যাগ থেকে পাওয়া যেতে পারে:
<meta name="_csrf" content="${_csrf.token}" /> <meta name="_csrf_header" content="${_csrf.headerName}" />
4. CSRF Protection কাস্টমাইজেশন
i. CSRF নিষ্ক্রিয় করা (API এর জন্য):
CSRF Protection API এর ক্ষেত্রে সাধারণত নিষ্ক্রিয় রাখা হয়, কারণ API-তে stateful session ব্যবহার হয় না।
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // Disable CSRF for APIs
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic(); // For basic authentication
}
ii. নির্দিষ্ট URL এর জন্য CSRF বাদ দেওয়া:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/api/**") // Ignore CSRF for specific endpoints
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
5. Custom CSRF Token Repository
Spring Security ডিফল্ট HttpSessionCsrfTokenRepository ব্যবহার করে টোকেন সংরক্ষণের জন্য। এটি কাস্টমাইজ করা সম্ভব।
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CustomCsrfTokenRepository implements CsrfTokenRepository {
@Override
public CsrfToken generateToken(HttpServletRequest request) {
return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", UUID.randomUUID().toString());
}
@Override
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
// Custom logic to save the token
}
@Override
public CsrfToken loadToken(HttpServletRequest request) {
// Custom logic to load the token
return null;
}
}
কাস্টম রেপোসিটরি Spring Security কনফিগারেশনে যুক্ত করা:
http
.csrf()
.csrfTokenRepository(new CustomCsrfTokenRepository());
6. CSRF Token Validation Failure Handling
CSRF টোকেন যাচাই ব্যর্থ হলে কাস্টম হ্যান্ডলার যোগ করতে পারেন:
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
import org.springframework.security.web.csrf.CsrfException;
import org.springframework.security.web.csrf.InvalidCsrfTokenException;
import org.springframework.security.web.csrf.MissingCsrfTokenException;
@Configuration
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
if (accessDeniedException instanceof MissingCsrfTokenException) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "CSRF Token Missing!");
} else if (accessDeniedException instanceof InvalidCsrfTokenException) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid CSRF Token!");
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied!");
}
}
}
7. Spring Security CSRF Protection এর Best Practices
- API এর ক্ষেত্রে CSRF Protection নিষ্ক্রিয় রাখুন: API-তে সাধারণত stateless authentication (JWT) ব্যবহৃত হয়।
- CSRF Token সবসময় ব্যবহার করুন: HTML ফর্ম সাবমিশনের জন্য।
- Custom Error Pages যোগ করুন: যাতে ব্যবহারকারী স্পষ্ট ত্রুটি বার্তা পায়।
- HTTP Headers নিশ্চিত করুন: AJAX এবং API কলের জন্য।
8. উপসংহার
CSRF Protection হল Spring Security এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য যা অননুমোদিত অনুরোধ প্রতিরোধ করতে সাহায্য করে। ডিফল্ট কনফিগারেশন অনেক ক্ষেত্রেই যথেষ্ট হলেও, প্রয়োজন অনুযায়ী এটি কাস্টমাইজ করা যায়। নিরাপত্তা বাড়ানোর জন্য CSRF Protection সর্বদা সচল রাখা উচিত, বিশেষ করে stateful ওয়েব অ্যাপ্লিকেশনগুলির জন্য।
Read more